<?php
use Think\Log;
define("TOKEN","weixin");
$weichat=new Weichat_base_api();

if(!isset($_GET['echostr'])){
	//调用响应消息函数
	$weichat->responseMsg();
}else{
	//实现网址接入，调用验证消息函数
	$weichat->valid();
}

class Weichat_base_api
{
//验证消息
function valid(){
	if ($this->checkSignature()) {
		$echostr=$_GET['echostr'];
ob_clean();
		echo $echostr;
		exit;
	}
	else{
		echo "error";
		exit;
	}
}
//检查签名
function checkSignature()
{
	//获取微信服务器GET请求的4个参数
	$signature=$_GET['signature'];
	$timestamp=$_GET['timestamp'];
	$nonce=$_GET['nonce'];
	$echostr=$_GET['echostr'];
	//定义一个数组，存储其中三个参数，分别是timestamp，nonce，token
	$tempArr=array($timestamp,$nonce,TOKEN);
	//进行排序
	sort($tempArr,SORT_STRING);
	//将数组转换成字符串
	$tempStr=implode($tempArr);
	//进行sha1加密算法
	$tempStr=sha1($tempStr);
	//判断请求是否来自微信服务器，对比$tempStr,signature
	if ($tempStr==$signature) {
		return true;
	}else{
		return false;
	}
}

//响应消息
function responseMsg(){
	//根据用户传过来的消息类型进行不同的响应
	//1.接收微信服务器POST过来的数据，XML数据包
		$postData=$GLOBALS[HTTP_RAW_POST_DATA];
		if(!$postData){
			echo "error";
			exit();
		}
	//2.解析XML数据包
		$object=simplexml_load_string($postData,"simpleXMLElement",LIBXML_NOCDATA);
	//获取消息类型
		$MsgType=$object->MsgType;
		switch ($MsgType) {

	case 'event':
		echo $this->receiveEvent($object);
		break;
	case 'text':
		//接收文本消息
		echo $this->receiveText($object);
		break;
	case 'image':
		//接收图片消息
		echo $this->receiveImage($object);
		break;
	case 'location':
		//接收地理位置消息
		echo $this->receiveLocation($object);
		break;
	case 'voice':
		//接收语音消息
		echo $this->receiveVoice($object);
		break;
	case 'video':
		//接收视频消息
		echo $this->receiveVideo($object);
		break;
	case 'link':
		//接收链接消息
		echo $this->receiveLink($object);
		break;
	default:
		break;
}
}



//接收事件推送
	function receiveEvent($obj){
		//数据库调取关注推送图文数据
		$hellotype="hello";
		$datainfo=M('we_reply')->where("we_reply_type='".$hellotype."'")->find();
		Log::write("获取的关注推送数据:【".json_encode($datainfo)."】");
		switch ($obj->Event) {
			case 'subscribe':
				if ($datainfo['we_hello_type']==2)
				{
					$dataArray=array(
						array(
							"Title"=>"{$datainfo['we_replynews_title']}",
							"Description"=>"{$datainfo['we_replynews_abs']}",
							"PicUrl"=>"http://wx.winneroad.cn/charitable/Public/{$datainfo['we_replynews_image']}",
							"Url"=>"{$datainfo['we_replynews_url']}"
						)

					);
					echo $this->replyNews($obj,$dataArray);
				}
				else
				{
					$replyMsg=$datainfo['we_replytext_content'];
					echo $this->replyText($obj,$replyMsg);

				}
				break;
			//取消关注事件
			case 'unsubscribe':
				//相关处理
                /*获取openid，
                 *如果被推荐人存在staff_recom,将isconcern置1
                 */
				break;
			//扫描二维码用户已关注事件
			case 'SCAN':
			//获取$obj->EventKeyj
			
				break;
			//自定义菜单事件
			case 'CLICK':
				//$keyword=$obj->EventKey;//消息类型
				$FunKey=$obj->EventKey;
				Log::write("获取的点击值:【".json_encode($FunKey)."】");
				$KeyMsg= M("we_reply")->where("we_reply_key='".$FunKey."'")->find();
				Log::write("获取的点击值:【".json_encode($KeyMsg)."】");
				if($KeyMsg["we_reply_type"]=='text') {
					//回复文字
					Log::write("回复文字");
					$redata = $this->replyText($obj, $KeyMsg["we_replytext_content"]);
					echo $redata;
				}
				elseif($KeyMsg["we_reply_type"]=='news')
				{
					Log::write("回复图片");
					$dataArray=array(
						array(
							"Title"=>"{$KeyMsg['we_replynews_title']}",
							"Description"=>"{$KeyMsg['we_replynews_abs']}",
							"PicUrl"=>"http://wx.winneroad.cn/charitable/Public/{$KeyMsg['we_replynews_image']}",
							"Url"=>"{$KeyMsg['we_replynews_url']}"
						)
					);
					return $this->replyNews($obj,$dataArray);
				}
				break;

			case 'VIEW':
				//$keyword=$obj->EventKey;//消息类型
				$FunKey=$obj->EventKey;
				$KeyMsg= M("we_reply")->where("we_reply_key='".$FunKey."'")->find();
				//回复图文
				echo $this->replyCustom($obj,$KeyMsg["we_replynews_url"]);
				break;

			default:
				$replyMsg="未定义事件";
				break;
		}
	}
//接收链接消息
function receiveLink($obj){
	//获取链接消息内容
	$linkArr=array(
				"Title"=>$obj->Title,
				"Description"=>$obj->Description,
				"Url"=>$obj->Url
			);
	//回复文本消息，可以自己随意编辑回复内容
	return $this->replyText($obj,"你发的链接地址是{$linkArr['Url']}");
}
//接收视频消息
function receiveVideo($obj){
	//获取视频消息内容
		$videoArr=array(
				"MediaId"=>$obj->MediaId
			);
		return $this->replyVideo($obj,$videoArr);
}
//接收语音消息
function receiveVoice($obj){
	//获取语音消息内容
	$voiceArr=array(
			"MediaId"=>$obj->MediaId,
			"Format"=>$obj->Format
		);
	//回复语音消息
	return $this->replyVoice($obj,$voiceArr);
}
//接收地理位置消息
function receiveLocation($obj){
	//获取地理位置消息内容
	$locationArr=array(
			"Location_X"=>"地理位置纬度：".$obj->Location_X,
			"Location_Y"=>"地理位置经度：".$obj->Location_Y,
			"Label"=>$obj->Label
		);
	return $this->replyText($obj,$locationArr['Label']);
}
//接收图片消息
function receiveImage($obj){
	//获取图片消息内容
	$imageArr=array(
		"PicUrl"=>$obj->PicUrl,
		"MediaId"=>$obj->MediaId
		);
	//发送图片消息
	return $this->replyImage($obj,$imageArr);
}
//接收文本消息
function receiveText($obj){
	
	//获取用户发送文本消息的内容:关键字
	$keyword=$obj->Content;
	$info=M('we_reply')->where("we_reply_key='".$keyword."'")->find();
	if ($info['we_reply_type']=='text') 
	{
		//文本关键字回复
		$content=$info['we_replytext_content'];
		return $this->replyText($obj,$content);
	}
	elseif($info['we_reply_type']=='news')
	{
		//关键字回复图文消息
		$dataArray=array(
				array(
					"Title"=>"{$info['we_replynews_title']}",
					"Description"=>"{$info['we_replynews_abs']}",
					"PicUrl"=>"http://wx.winneroad.cn/charitable/Public/{$info['we_replynews_image']}",
					"Url"=>"{$info['we_replynews_url']}"
					)
			);
		
		return $this->replyNews($obj,$dataArray);
	}
	else
	{
		$reply_text='text';
		$reply_news='news';
		$nowkeywords=M('we_reply')->where("we_reply_type='".$reply_text."' or we_reply_type='".$reply_news."'")->field('we_reply_key')->select();
		Log::write("可以回复的关键字：[".json_encode($nowkeywords)."]");
        $content = "请回复以下关键字：\n";
        foreach($nowkeywords as $v){
            $content.=$v['we_reply_key'].'.'."\n";
        }
		return $this->replyText($obj,$content);
	}
}





///自定义菜单回复
function replyCustom($obj,$content)
{
	$replyXml="<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[%s]]></Event>
<EventKey><![CDATA[%s]]></EventKey>
</xml>";
	//返回一个XML数据包
	$resultStr=sprintf($replyXml,$obj->ToUserName,$obj->FromUserName,time(),$obj->Event,$content);
	return $resultStr;
}



//回复文本消息
function replyText($obj,$content){
	$replyXml="<xml>
			<ToUserName><![CDATA[%s]]></ToUserName>
			<FromUserName><![CDATA[%s]]></FromUserName>
			<CreateTime>%s</CreateTime>
			<MsgType><![CDATA[text]]></MsgType>
			<Content><![CDATA[%s]]></Content>
			</xml>";
	//返回一个XML数据包
	$resultStr=sprintf($replyXml,$obj->FromUserName,$obj->ToUserName,time(),$content);
	return $resultStr;
}
//回复图片消息
function replyImage($obj,$imageArr){
	$replyXml="<xml>
			<ToUserName><![CDATA[%s]]></ToUserName>
			<FromUserName><![CDATA[%s]]></FromUserName>
			<CreateTime>%s</CreateTime>
			<MsgType><![CDATA[image]]></MsgType>
			<Image>
			<MediaId><![CDATA[%s]]></MediaId>
			</Image>
			</xml>";
	//返回一个XML数据包
	$resultStr=sprintf($replyXml,$obj->FromUserName,$obj->ToUserName,time(),$imageArr['MediaId']);
	return $resultStr;
}
//回复语音消息
function replyVoice($obj,$voiceArr){
	$replyXml="<xml>
			<ToUserName><![CDATA[%s]]></ToUserName>
			<FromUserName><![CDATA[%s]]></FromUserName>
			<CreateTime>%s</CreateTime>
			<MsgType><![CDATA[voice]]></MsgType>
			<Voice>
			<MediaId><![CDATA[%s]]></MediaId>
			</Voice>
			</xml>";
	//返回一个XML数据包
	$resultStr=sprintf($replyXml,$obj->FromUserName,$obj->ToUserName,time(),$voiceArr['MediaId']);
	return $resultStr;
}
//回复视频消息
function replyVideo($obj,$videoArr){
	$replyXml="<xml>
			<ToUserName><![CDATA[%s]]></ToUserName>
			<FromUserName><![CDATA[%s]]></FromUserName>
			<CreateTime>%s</CreateTime>
			<MsgType><![CDATA[video]]></MsgType>
			<Video>
			<MediaId><![CDATA[%s]]></MediaId>
			</Video> 
			</xml>";
	//返回一个XML数据包
	$resultStr=sprintf($replyXml,$obj->FromUserName,$obj->ToUserName,time(),$videoArr['MediaId']);
	return $resultStr;

}


//回复音乐消息
function replyMusic($obj,$musicArr){
	$replyXml="<xml>
			<ToUserName><![CDATA[%s]]></ToUserName>
			<FromUserName><![CDATA[%s]]></FromUserName>
			<CreateTime>%s</CreateTime>
			<MsgType><![CDATA[music]]></MsgType>
			<Music>
			<Title><![CDATA[%s]]></Title>
			<Description><![CDATA[%s]]></Description>
			<MusicUrl><![CDATA[%s]]></MusicUrl>
			<HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
			<ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
			</Music>
			</xml>";
	//返回一个XML数据包
	$resultStr=sprintf($replyXml,$obj->FromUserName,$obj->ToUserName,time(),$musicArr['Title'],$musicArr['Description'],$musicArr['MusicUrl'],$musicArr['HQMusicUrl'],$musicArr['ThumbMediaId']);
	return $resultStr;
}
//回复图文消息
function replyNews($obj,$newsArr){
	$itemStr="";
	if (is_array($newsArr)) {
		foreach ($newsArr as $item) {
			$itemXml="<item>
			<Title><![CDATA[%s]]></Title> 
			<Description><![CDATA[%s]]></Description>
			<PicUrl><![CDATA[%s]]></PicUrl>
			<Url><![CDATA[%s]]></Url>
			</item>";
			$itemStr.=sprintf($itemXml,$item['Title'],$item['Description'],$item['PicUrl'],$item['Url']);
		}
	}

	$replyXml="<xml>
			<ToUserName><![CDATA[%s]]></ToUserName>
			<FromUserName><![CDATA[%s]]></FromUserName>
			<CreateTime>%s</CreateTime>
			<MsgType><![CDATA[news]]></MsgType>
			<ArticleCount>%s</ArticleCount>
			<Articles>{$itemStr}</Articles>
			</xml>";
	//返回一个XML数据包
	$resultStr=sprintf($replyXml,$obj->FromUserName,$obj->ToUserName,time(),count($newsArr));
	return $resultStr;
}




	private $_appid;
	private $_appsecret;
	
	//表示QRCode的类型
	const QRCODE_TYPE_TEMP = 1;
	const QRCODE_TYPE_LIMIT = 2;
	const QRCODE_TYPE_LIMIT_STR = 3;
	
	
	// public function __construct($id,$secret){
	// 	$this->_appid = $id;
	// 	$this->_appsecret = $secret;
	// }
	/*
	 * 获取 access_token
	 * @param	string	$token_file	用来存储token的临时文件
	 */
	public function getAccessToken($token_file='./access_token'){
		//考虑过期问题，将获取到的access_tonken存储到某个文件中
		$life_time = 7200;
		if(file_exists($token_file) && time()-filemtime($token_file)<$life_time){
			//存在有效的access_token
			return file_get_contents($token_file);
		}
		//目标URL
		$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->_appid}&secret={$this->_appsecret}";
		//向该目标发送GET请求
		$result = $this->_requestGet($url);
		if(!$result){
			return FALSE;
		}
		//存在返回响应结果
		$result_obj = json_decode($result);
		//存入token_file中
		file_put_contents($token_file, $result_obj->access_token);
		return $result_obj->access_token;
	}
	
	
	/**
	 *获取二维码ticket 
	 *@param	$content	内容
	 *@param	$type		QR码类型（1：临时，2：永久，3：永久字符串）
	 *@param	$expire		有效期，临时的QR码就可以更改该参数
	 */
	private function _getQRCodeTicket($content,$type=1,$expire=2592000){
		$access_token = $this->getAccessToken();
		$url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=$access_token";
		$type_list = array(
			self::QRCODE_TYPE_TEMP => 'QR_SCENE',
			self::QRCODE_TYPE_LIMIT => 'QR_LIMIT_SCENE',
			self::QRCODE_TYPE_LIMIT_STR => 'QR_LIMIT_STR_SCENE'
			);
		$action_name = $type_list[$type];
		switch($type){
			case self::QRCODE_TYPE_TEMP:
				$data_arr['action_name'] = $action_name;
				$data_arr['expire_seconds'] = $expire;
				$data_arr['action_info']['scene']['scene_id'] = $content;
				break;
			case self::QRCODE_TYPE_LIMIT:
				$data_arr['action_name'] = $action_name;
				$data_arr['action_info']['scene']['scene_id'] = $content;
				break;
			case self::QRCODE_TYPE_LIMIT_STR:
				$data_arr['action_name'] = $action_name;
				$data_arr['action_info']['scene']['scene_str'] = "$content";
				break;		
		}
		$data = json_encode($data_arr);
		//echo $data;
		$result = $this->_requestPost($url,$data);
		if(!$result){
			return FALSE;
		}
		//存在处理响应数据
		$result_obj = json_decode($result);
		return $result_obj->ticket;
	}
	
	/**
	 *获取二维码
	 *@param	$content	内容int/string
	 *@param  	$file		储存为文件的地址
	 *@param	$type		QR码类型（1：临时，2：永久，3：永久字符串）
	 *@param	$expire		有效期，临时的QR码就可以更改该参数int
	 */
	public function getQRCode($content,$type=1,$file=NULL,$expire=2592000){
		$ticket = $this->_getQRCodeTicket($content,$type,$expire);
		$url = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket='.$ticket;
		$result = $this->_requestGet($url);//此时result就是图像内容
		if($file){
			file_put_contents($file,$result);
		}else{
			header('Content-Type: image/jpeg');
			echo $result;
		}
	}
	
	private function _requestPost($url,$data,$ssl=true){
		//curl完成
		$curl = curl_init();
		//设置curl选项
		curl_setopt($curl, CURLOPT_URL, $url);
		$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0';//请求代理信息
		curl_setopt($curl, CURLOPT_USERAGENT, $user_agent);
		curl_setopt($curl, CURLOPT_AUTOREFERER, true);
		if($ssl){
			curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
		}
		//处理post相关任务
		curl_setopt($curl, CURLOPT_POST, true);//是否为post请求
		curl_setopt($curl, CURLOPT_POSTFIELDS, $data);//处理请求数据
		//处理响应结果
		curl_setopt($curl, CURLOPT_HEADER, false);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		
		//发送请求
		$response = curl_exec($curl);
		if(false===$response){
			echo curl_error($curl);
			return false;
		}
		return $response;
	}	
	
	
	
	/*
	 * 发送get请求的方法
	 * @param	string	$url	目标URL
	 * @param	bool	$ssl	是否为https协议
	 * @return	string	响应主体Content
	 */
	private function _requestGet($url,$ssl=true){
		//curl完成
		$curl = curl_init();
		//设置curl选项
		curl_setopt($curl, CURLOPT_URL, $url);
		$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0';//请求代理信息
		curl_setopt($curl, CURLOPT_USERAGENT, $user_agent);
		curl_setopt($curl, CURLOPT_AUTOREFERER, true);
		if($ssl){
			curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
		}
		curl_setopt($curl, CURLOPT_HEADER, false);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
		
		//发送请求
		$response = curl_exec($curl);
		if(false===$response){
			echo curl_error($curl);
			return false;
		}
		return $response;
		
	}



}








?>